using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Developex.GenerateClassOnShema.Classes
{
	public class DbSettings
	{
		private Dictionary<string, TableSettings> TableSettings;

		#region Public Functions

		public string GetTableClassName(string tableName)
		{
			return TableSettings[tableName.ToUpper()].ClassName;
		}

		public TableSettings GetTableSettings(string tableName)
		{
			tableName = tableName.ToUpper();
			if (!TableSettings.ContainsKey(tableName))
				return null;
			return TableSettings[tableName];
		}

		public bool ContainsTable(string tableName)
		{
			tableName = tableName.ToUpper();
			return TableSettings.ContainsKey(tableName);
		}

		public IEnumerable<TableSettings> GetAllTableSettings()
		{
			return TableSettings.Values;
		}

		#endregion

		public string NameSpace;
		public string IndentSize;
		public bool IsCE;
		public bool IsSql2000;
		public bool AddEncodedProperty;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="nameSpace"></param>
		/// <param name="indentSize"></param>
		/// <param name="CE"></param>
		/// <param name="addEncoded"></param>
		/// <param name="isSql2000"></param>
		public DbSettings(string nameSpace, string indentSize, bool CE, bool addEncoded, bool isSql2000)
		{
			NameSpace = nameSpace;
			IndentSize = indentSize;
			IsCE = CE;
			AddEncodedProperty = addEncoded;
			IsSql2000 = isSql2000;
		}

		#region ReadFromIniFile

		public void ReadFromIniFile(string iniFileName)
		{
			List<string> lines = GetProprocessedData(iniFileName);
			TableSettings = new Dictionary<string, TableSettings>();
			TableSettings ts = null;
			for (int i = 0; i < lines.Count; )
			{
				string line = lines[i++];
				if (line == "[*")
				{
					if (ts == null)
						throw new InvalidDataException("Ini file has incorrect format: not closed line");
					// table properties
					StringBuilder sb = new StringBuilder();
					bool br = false;
					while (i < lines.Count)
					{
						line = lines[i++];
						if (line == "*]")
						{
							br = true;
							break;
						}
						sb.AppendLine(line);
					}
					if (!br)
						throw new InvalidDataException("Ini file has incorrect format: not closed line");
					if (!ts.LoadFromData(sb.ToString()))
						throw new InvalidDataException("Ini file has incorrect format");
				}
				else
				{
					string[] ss = line.Split('=');
					if (ss.Length != 2)
						throw new InvalidDataException("Ini file has incorrect format, line:\r\n" + line);
					ts = new TableSettings(ss[0].Trim(), ss[1].Trim());
					TableSettings.Add(ts.TableName.ToUpper(), ts);
				}
			}


			// TODO: implement new, convert from old format
			// Deprecated
			//DbSettings settings = new DbSettings(classNamespace, databaseWrapperNamespacePrefix);
			//using (FileStream fs = File.OpenRead(iniFileName))
			//{
			//    StreamReader sr = new StreamReader(fs);
			//    while (!sr.EndOfStream)
			//    {
			//        string line = sr.ReadLine().Trim();
			//        if (string.IsNullOrEmpty(line))
			//            continue;

			//        if (line[0] == '[')
			//        {
			//            if (classWithProperties == null)
			//                throw new InvalidOperationException("Ini file has incorrect format (after \"table=class\" line must be 0 or 1 properties blocks) , line data=" + line);

			//            int pos = 1;
			//            classWithProperties.properties = new List<ClassProperties>();
			//            ReadClassProperties(ref line, ref pos, sr, classWithProperties.properties);

			//            classWithProperties = null;
			//            continue;
			//        }

			//        string[] ss = line.Split('=');
			//        if (ss.Length != 2)
			//            throw new InvalidOperationException("Ini file has incorrect format, line data=" + line);

			//        classWithProperties = new ClassWithProperties();
			//        classWithProperties.className = ss[1].Trim();

			//        settings.TableSettings[ss[0].Trim()] = classWithProperties;
			//    }
			//    sr.Close();
			//}
		}

		private List<string> GetProprocessedData(string iniFileName)
		{
			if (string.IsNullOrEmpty(iniFileName))
				throw new InvalidOperationException("Empty file name");
			if (!File.Exists(iniFileName))
				throw new InvalidOperationException("File " + iniFileName + "does not exist");
			List<string> lines = new List<string>();
			using (StreamReader sr = File.OpenText(iniFileName))
			{
				while (sr.Peek() != -1)
				{
					string line = sr.ReadLine();
					if (string.IsNullOrEmpty(line))
						continue;
					line = line.Trim();
					if (line.StartsWith("'"))
						continue;
					if (line.StartsWith("#include "))
					{
						string fileName = line.Substring(9);
						if (string.IsNullOrEmpty(fileName))
							throw new InvalidOperationException("Empty file name in #include option (" + iniFileName + ")");
						if (!File.Exists(fileName))
							throw new InvalidOperationException("File " + fileName + "does not exist (" + iniFileName + ")");
						lines.AddRange(GetProprocessedData(fileName));
					}
					else lines.Add(line);
				}
			}
			return lines;
		}

		#endregion
	}
}
